package ccm.component.menu;

import ccm.common.ReceiveDataEvent;
import ccm.common.ReceiveDataListener;
import ccm.component.oscilloscope.OscilloscopeDataManager;
import ccm.component.override.VFlowLayout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

public class MenuJPanel extends JPanel implements ActionListener, OscilloscopeDataManager, ReceiveDataListener
{
    private final int[]                 receiveBuf;
    public        ReceiveDataListener   a;
    private       ArrayList<DataFrame>  dataFrames;
    private       HashMap<Long,Integer> dataFramesXMap;
    private       DataItem[]            datas;
    private       PageItem[]            pages;
    private       JPanel                pageJButtonsJPanel;
    private       JPanel                pageJPanel;
    private       int                   receiveBufEnd=0;
    private       CardLayout            pageJPanelCardLayout;

    MenuJPanel()
    {
        super(new BorderLayout());
        dataFrames    =new ArrayList<>();
        dataFramesXMap=new HashMap<>();
        receiveBuf    =new int[8192];

        // JScrollPane jScrollPane=new JScrollPane();
        // this.add(jScrollPane,BorderLayout.WEST);
        // jScrollPane.setLayout(new ScrollPaneLayout());
        pageJButtonsJPanel=new JPanel();
        add(pageJButtonsJPanel,BorderLayout.WEST);
        // pageJButtonsJPanel.setPreferredSize(new Dimension(300,1000));
        pageJButtonsJPanel.setLayout(new VFlowLayout());
        pageJPanel=new JPanel();
        pageJPanel.setLayout(pageJPanelCardLayout=new CardLayout());
        this.add(pageJPanel,BorderLayout.CENTER);
    }

    public int getDataColumn()
    {
        return datas.length;
    }

    public void clear()
    {
        dataFrames.clear();
        dataFramesXMap.clear();
    }

    public int getDataLength()
    {
        return dataFrames.size();
    }

    public String getColumnName(int column)
    {
        if(datas[column]==null)
            return "";
        return datas[column].name;
    }

    public boolean isColumnEnabled(int i,int column)
    {
        return dataFrames.get(i).map[column]!=-1;
    }

    public float getY(int i,int column)
    {
        DataFrame d=dataFrames.get(i);
        return d.data[d.map[column]].floatValue();
    }

    public long getTimeUs(int i)
    {
        return 0;
    }

    public double getX(int i)
    {
        return dataFrames.get(i).usTick;
    }

    public int getClosestI(double x)
    {
        return dataFramesXMap.get((long)x);
    }

    public double getClosestY(int i,int column)
    {
        for(int j=0, length=getDataLength();j<100;++j)
            if(i+j<length&&isColumnEnabled(i+j,column))
                return getY(i+j,column);
            else if(i-j>=0&&isColumnEnabled(i-j,column))
                return getY(i-j,column);
        return 0;
    }

    synchronized public MenuJPanel clone()
    {
        try
        {
            return (MenuJPanel)super.clone();
        }catch(CloneNotSupportedException ex)
        {
            ex.printStackTrace();
        }
        return null;
    }

    synchronized public void receiveData(ReceiveDataEvent event)
    {
        for(byte datum: event.getData())
        {
            receiveBuf[receiveBufEnd]=Byte.toUnsignedInt(datum);
            ;
            ++receiveBufEnd;
            if(receiveBufEnd>=receiveBuf.length)
                receiveBufEnd=0;
            if(receiveBufEnd>=2&&receiveBuf[receiveBufEnd-2]=='\r'&&receiveBuf[receiveBufEnd-1]=='\n')
            {
                if(receiveBuf[0]==0&&receiveBuf[1]==0&&receiveBuf[2]==1)//Info
                {
                    int cur=3;
                    pages=new PageItem[receiveBuf[cur]];
                    cur+=1;
                    datas=new DataItem[(receiveBuf[cur]&0XFF)|((receiveBuf[cur+1]&0XFF)<<8)];
                    cur+=2;
                    //接收页码信息
                    for(int i=0;i<pages.length;++i)
                    {
                        int len=receiveBuf[cur];
                        cur+=1;
                        byte[] name=new byte[len];
                        for(int j=0;j<len;name[j]=(byte)receiveBuf[cur],cur+=1,++j)
                            ;

                        pages[i]=new PageItem(new String(name));
                    }
                    // System.out.println(Arrays.toString(pages));
                    //前SCNS_MENU_MAX_PAGE个默认是页码,不发
                    for(int i=pages.length;i<datas.length;++i)
                    {
                        int len=receiveBuf[cur];
                        cur+=1;
                        byte[] name=new byte[len];
                        for(int j=0;j<len;name[j]=(byte)receiveBuf[cur],cur+=1,++j)
                            ;
                        int savePage=((receiveBuf[cur]&0XFF)|((receiveBuf[cur+1]&0XFF)<<8));
                        cur+=2;
                        boolean canModify=receiveBuf[cur]==1;
                        cur+=1;
                        int page=receiveBuf[cur];
                        cur+=1;
                        ScnsType type=new ScnsType(receiveBuf[cur]);
                        cur+=1;
                        datas[i]=new DataItem(new String(name),savePage,canModify,page,type);
                    }
                    System.out.println(Arrays.toString(datas));

                    System.out.println(receiveBufEnd);
                    // System.out.println(cur);
                    // System.out.println(receiveBufEnd);
                    update();
                    a.receiveData(new ReceiveDataEvent(this,""));
                }
                else if(receiveBuf[0]==0&&receiveBuf[1]==0&&receiveBuf[2]==2&&pages!=null&&datas!=null)//Data
                {
                    int cur=3;
                    DataFrame dataFrame=new DataFrame(((long)(receiveBuf[cur]&0XFF)|((long)(receiveBuf[cur+1]&0XFF)<<8)|((long)(receiveBuf[cur+2]&0XFF)<<16)|((long)(receiveBuf[cur+3]&0XFF)<<24)|((long)(receiveBuf[cur+4]&0XFF)<<32)|((long)(receiveBuf[cur+5]&0XFF)<<40)|((long)(receiveBuf[cur+6]&0XFF)<<48)|((long)(receiveBuf[cur+7]&0XFF)<<56)),(receiveBuf[cur+8]&0XFF)|((receiveBuf[cur+9]&0XFF)<<8));
                    cur+=10;
                    System.out.println(dataFrame.map.length);
                    for(int i=0;i<dataFrame.map.length;++i)
                    {

                        dataFrame.map[(receiveBuf[cur]&0XFF)|((receiveBuf[cur+1]&0XFF)<<8)]=i;
                                                                                            cur+=2;
                        switch(datas[dataFrame.map[i]].type.getType())
                        {
                            case ScnsType.INT8:
                            case ScnsType.UINT8:
                            case ScnsType.INT16:
                            case ScnsType.UINT16:
                            case ScnsType.INT32:
                            {
                                dataFrame.data[i]=(receiveBuf[cur]&0XFF)|((receiveBuf[cur+1]&0XFF)<<8)|((receiveBuf[cur+2]&0XFF)<<16)|((receiveBuf[cur+3]&0XFF)<<24);
                                cur+=4;
                                break;
                            }
                            case ScnsType.DOUBLE:
                            case ScnsType.FLOAT:
                            {
                                dataFrame.data[i]=Float.intBitsToFloat((receiveBuf[cur]&0XFF)|((receiveBuf[cur+1]&0XFF)<<8)|((receiveBuf[cur+2]&0XFF)<<16)|((receiveBuf[cur+3]&0XFF)<<24));
                                cur+=4;
                                break;
                            }
                        }
                        datas[dataFrame.map[i]].carValueJLabel.setText(dataFrame.data[i].toString());
                    }


                    dataFrames.add(dataFrame);
                    System.out.println(dataFrame);
                }
                else
                {

                }


                receiveBufEnd=0;
            }
        }
    }

    private void update()
    {
        pageJButtonsJPanel.removeAll();
        pageJPanel.removeAll();
        for(PageItem page: pages)
            if(page.name.length()!=0)
            {
                pageJButtonsJPanel.add(page.jButton);
                pageJPanel.add(page.jPanel,page.name);
                page.jPanel.removeAll();
            }
        pageJButtonsJPanel.revalidate();
        pageJPanel.revalidate();

        for(DataItem data: datas)
            if(data!=null)
            {
                int page=data.page;
                pages[page].jPanel.add(data.jPanel);
            }
        // for(int i=0;i<pages.length;++i)
        // if(pages[i].name.length()!=0)
        // pages[i].jPanel.setLayout(new GridLayout(cnt[i],1));

    }

    public void actionPerformed(ActionEvent e)
    {
    }

    private class DataItem
    {
        String   name;
        int      savePage;
        boolean  canModify;
        ScnsType type;
        int      page;

        JPanel jPanel;
        JLabel carValueJLabel;


        public DataItem(String name,int savePage,boolean canModify,int page,ScnsType type)
        {
            this.name     =name;
            this.savePage =savePage;
            this.canModify=canModify;
            this.page     =page;
            this.type     =type;

            jPanel=new JPanel();
            jPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
            if(type.equals(ScnsType.FUNCTION))
            {
                JButton jButton=new JButton(this.name);
                jPanel.add(jButton);
                jButton.addActionListener(MenuJPanel.this);
            }
            else
            {
                JLabel nameJLabel=new JLabel(this.name);
                nameJLabel.setPreferredSize(new Dimension(nameJLabel.getFont().getSize()*12,(int)(nameJLabel.getFont().getSize()*1.2)));
                jPanel.add(nameJLabel);
                nameJLabel.setToolTipText("类型:"+this.type+((savePage==0XFFFF)?"":"保存于:"+savePage));
                carValueJLabel=new JLabel();
                jPanel.add(carValueJLabel);
                carValueJLabel.setPreferredSize(new Dimension(carValueJLabel.getFont().getSize()*12,(int)(carValueJLabel.getFont().getSize()*1.2)));
            }
        }

        public String toString()
        {
            return "DataItem{"+"name='"+name+'\''+", savePage="+savePage+", canModify="+canModify+", page="+page+", type="+type+'}';
        }
    }

    private class PageItem implements ActionListener
    {
        String  name;
        JButton jButton;
        JPanel  jPanel;

        public PageItem(String name)
        {
            this.name=name;
            if(this.name.length()!=0)
            {
                jButton=new JButton(this.name);
                jButton.addActionListener(this);
                jPanel=new JPanel();
                jPanel.setLayout(new VFlowLayout());
            }
        }

        public String toString()
        {
            return "PageItem{"+"name='"+name+'\''+'}';
        }

        public void actionPerformed(ActionEvent e)
        {
            if(e.getSource() instanceof JButton)
                pageJPanelCardLayout.show(pageJPanel,((JButton)e.getSource()).getText());
        }
    }

    private class DataFrame
    {
        long     usTick;
        int      map[];
        Number[] data;

        DataFrame(long usTickIn,int len)
        {
            usTick=usTickIn;
            map   =new int[datas.length];
            data  =new Number[len];
        }

        public String toString()
        {
            return "DataFrame{"+"usTick="+usTick+", len="+map.length+", map="+Arrays.toString(map)+", data="+Arrays.toString(data)+'}';
        }
    }

}
